package l1j.william;

import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.TimeZone;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.Collection;

import l1j.opqlo.NewSystem.Play18La.Play18La;
import l1j.opqlo.Server.L1World.L1World;
import l1j.server.Config;
import l1j.server.GameServer.GameServer;
import l1j.server.Thread.GeneralThreadPool;
import l1j.server.server.model.Instance.L1PcInstance;
import l1j.server.server.model.game.L1BugBearRace;
import l1j.server.server.model.gametime.L1GameTime;
import l1j.server.server.model.gametime.L1GameTimeListener;
import l1j.server.server.serverpackets.S_SystemMessage;

public class L1GameReStart {
	private class TimeUpdaterRestar implements Runnable {
		@Override
		public void run() {
			while (true) {

				L1GameReStart.this._previousTime = L1GameReStart.this._currentTime;
				L1GameReStart.this._currentTime = new L1GameTime();
				L1GameReStart.this.notifyChanged();
				final int remnant = L1GameReStart.this.GetRestartTime() * 60;
				System.out.println("正在載入自動重開設定...完成! "+ L1GameReStart.this.GetRestartTime() + "分鐘後");
				while (remnant > 0) {

					for (int i = remnant; i >= 0; i--) {
						L1GameReStart.this.SetRemnant(i);
						willRestartTime = i;
						if (i % 60 == 0 && i <= 300 && i != 0) {
							L1GameReStart.this.BroadCastToAll("伺服器將於 " + i / 60+ " 分鐘後自動重啟,請至安全區域準備登出。");
							_log.log(Level.SEVERE, "伺服器將於 " + i / 60+ " 分鐘後重新啟動");
						} // TODO if (五分鐘內 一分鐘一次)
						else if (i <= 30 && i != 0) {
							if (Config.BugbearRace_Switch) {
								L1BugBearRace.getInstance().ServerReStart();// opqlo賭肥
								Config.BugbearRace_Switch = false;
							}
							Play18La.get().StopGame();
							L1GameReStart.this.BroadCastToAll("伺服器將於 " + i+ "秒後重新啟動,煩請儘速下線！");
							_log.log(Level.SEVERE, "伺服器將於 " + i + " 秒後重新啟動");
						} // TODO else if (30秒內 一秒一次)
						else if (i == 0) {
							L1GameReStart.this.BroadCastToAll("伺服器自動重啟。");
							System.out.println("伺服器重新啟動。");
							GameServer.getInstance().shutdown(); // TODO 修正自動重開角色資料會回溯
							System.exit(1);
						} // TODO if (1秒)
						try {
							Thread.sleep(1000);
						} catch (final InterruptedException e) {
							_log.log(Level.SEVERE, e.getLocalizedMessage(), e);
						}
					}
				}
			}
		}
	}

	private static Logger _log = Logger.getLogger(L1GameReStart.class.getName());
	private static L1GameReStart _instance;

	public static int getWillRestartTime() {
		return willRestartTime;
	}

	public static void init() {
		_instance = new L1GameReStart();
	}

	private volatile L1GameTime _currentTime = new L1GameTime();
	private L1GameTime _previousTime = null;

	private final List<L1GameTimeListener> _listeners = new CopyOnWriteArrayList<L1GameTimeListener>();

	private static int willRestartTime;

	public static L1GameReStart getInstance() {
		return _instance;
	}

	public int _remnant;

	private L1GameReStart() {
		GeneralThreadPool.getInstance().execute(new TimeUpdaterRestar());
	}

	public void addListener(final L1GameTimeListener listener) {
		this._listeners.add(listener);
	}

	private void BroadCastToAll(final String string) {
		final Collection<L1PcInstance> allpc = L1World.getInstance().getAllPlayers();
		for (final L1PcInstance pc : allpc) {
			pc.sendPackets(new S_SystemMessage(string));
		}
	}

	public L1GameTime getGameTime() {
		return this._currentTime;
	}

	public int GetRemnant() {
		return this._remnant;
	}

	private int GetRestartTime() {
		final Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone(Config.TIME_ZONE));//以設定時區取得Calendar實例
		final Date trialTime = new Date();
		calendar.setTime(trialTime);
		int RestartHour = 6;
		final int nowHour = calendar.get(Calendar.HOUR);
		if (nowHour >= 6 && nowHour < 18) {
			RestartHour = 18;
		}
		calendar.clear(Calendar.HOUR_OF_DAY);
		calendar.clear(Calendar.MINUTE);
		calendar.clear(Calendar.SECOND);
		calendar.set(Calendar.HOUR, RestartHour);
		calendar.set(Calendar.MINUTE, 0);
		calendar.set(Calendar.SECOND, 0);

		return (int) ((calendar.getTime().getTime() - System.currentTimeMillis()) / 60000);
	}

	private boolean isFieldChanged(final int field) {
		return this._previousTime.get(field) != this._currentTime.get(field);
	}

	private void notifyChanged() {
		if (this.isFieldChanged(Calendar.MONTH)) {
			for (final L1GameTimeListener listener : this._listeners) {
				listener.onMonthChanged(this._currentTime);
			}
		}
		if (this.isFieldChanged(Calendar.DAY_OF_MONTH)) {
			for (final L1GameTimeListener listener : this._listeners) {
				listener.onDayChanged(this._currentTime);
			}
		}
		if (this.isFieldChanged(Calendar.HOUR_OF_DAY)) {
			for (final L1GameTimeListener listener : this._listeners) {
				listener.onHourChanged(this._currentTime);
			}
		}
		if (this.isFieldChanged(Calendar.MINUTE)) {
			for (final L1GameTimeListener listener : this._listeners) {
				listener.onMinuteChanged(this._currentTime);
			}
		}
	}

	public void removeListener(final L1GameTimeListener listener) {
		this._listeners.remove(listener);
	}

	public void SetRemnant(final int remnant) {
		this._remnant = remnant;
	}
}
